package cn.wangqi.personal.common;

import cn.wangqi.personal.domain.BlogUser;
import cn.wangqi.personal.service.IBlogUserService;
import org.apache.log4j.Logger;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;

/**
 * Created by admin on 2017/9/23.
 */
public class ShiroDbRealm extends AuthorizingRealm {

    private Logger logger = Logger.getLogger(ShiroDbRealm.class);

    public static final String SESSION_USER_KEY = "session_user";

    private IBlogUserService blogUserService;

    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof UsernamePasswordToken;
    }

    /**
     * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用,负责在应用程序中决定用户的访问控制的方法
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
        BlogUser blogUser = (BlogUser) SecurityUtils.getSubject().getSession().getAttribute(ShiroDbRealm.SESSION_USER_KEY);
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        return null;
    }

    /**
     * 认证回调函数，登录信息和用户验证信息验证
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(
            AuthenticationToken authcToken) throws AuthenticationException {
        logger.error("登录信息和用户信息验证");
        // 把token转换成User对象
        BlogUser userLogin = tokenToUser((UsernamePasswordToken) authcToken);
        // 验证用户是否可以登录
        BlogUser blogUser = blogUserService.findBlogUserByUserName(userLogin.getUserName());
        if(blogUser == null){
            throw new UnknownAccountException("无效的用户名");
        }
        if(blogUser.getLock()==1){
            throw new LockedAccountException("账号已被锁定");
        }
        SimpleAuthenticationInfo authenticationInfo = new SimpleAuthenticationInfo(
                blogUser.getUserName(), //用户名
                blogUser.getPassword(), //密码
                ByteSource.Util.bytes(blogUser.getCredentialsSalt()),//salt=username+salt
                getName()  //realm name
        );
        return authenticationInfo;
    }

    private BlogUser tokenToUser(UsernamePasswordToken authcToken) {
        BlogUser blogUser = new BlogUser();
        blogUser.setUserName(authcToken.getUsername());
        blogUser.setPassword(String.valueOf(authcToken.getPassword()));
        return blogUser;
    }

    public void setBlogUserService(IBlogUserService blogUserService) {
        this.blogUserService = blogUserService;
    }

    public IBlogUserService getBlogUserService() {
        return blogUserService;
    }
}